<?php

namespace common\observer;

use support\SingletonTrait;
use common\model\TaskModel;
use common\model\EntityModel;
use common\service\CommonService;
use common\service\StatusService;
use common\model\StepCategoryModel;
use teamones\dbeventObserver\interfaces\SplSubject;
use teamones\dbeventObserver\interfaces\SplObserver;

/**
 * 任务完成或者开始,同步到剧集状态
 */
class TaskStatusSyncToEpisode implements SplObserver
{
    use SingletonTrait;

    /**
     * @inheritDoc
     */
    function update(SplSubject $subject): void
    {
        $updateData = $subject->getSplUpdateData();
        if (!isset($updateData['task_status'])) {
            return;
        }

        $updateStatus = StatusService::getInstance()->getOne(['id' => $updateData['task_status']], '*');
        if (empty($updateStatus)) {
            return;
        }
        $defaultStartStatus = StatusService::getInstance()->getTaskDefaultStartStatus();
        $defaultDoneStatus = StatusService::getInstance()->getTaskDoneStatus();

        // 只处理开始和结束
        if (!in_array($updateData['task_status'], [$defaultStartStatus['id'], $defaultDoneStatus['id']])) {
            return;
        }
        $module = module_by_code('episode');
        $task = $subject->getSubjectData();
        $entity = model(EntityModel::class)->find($task['entity_id']);
        if (empty($entity)) {
            return;
        }

        $episode = model(EntityModel::class)->where(['project_id' => $entity['project_id'], 'module_id' => $module['id'], 'code' => $entity['initial_episode_code']])->find();
        if (empty($episode)) {
            return;
        }
        $episode['json'] = json_decode($episode['json'], true);

        switch ($updateStatus['code']) {
            case $defaultStartStatus['code']:
                $defaultStatus = StatusService::getInstance()->getTaskDefaultStatus();
                if (empty($episode['json']['episode_status']) || $episode['json']['episode_status'] == $defaultStatus['id']) {
                    // 剧集状态为空 直接更新为进行中
                    $this->updateEpisodeStatus($episode, $updateStatus);
                } else if ($episode['json']['episode_status'] == $defaultDoneStatus['id']
                    && (empty($episode['json']['episode_is_seal']) || $episode['json']['episode_is_seal'] == 'no')
                ) {
                    // 剧集状态为已完成 并且剧集没有封板  检查灯光特效的完成情况
                    $hasNotDoneShotTaskEpisodeCodeList = $this->checkEpisodeEfxLightTaskDoneStatus($episode);
                    if ($hasNotDoneShotTaskEpisodeCodeList['total'] > 0 && $hasNotDoneShotTaskEpisodeCodeList['undone'] > 0) {
                        // 有灯光特效任务 并且有未完成的灯光特效任务 那么就修改为进行中
                        $this->updateEpisodeStatus($episode, $updateStatus);
                    }
                }

                break;
            case $defaultDoneStatus['code']:
                // 检查是否所有的灯光特效任务都完成
                $hasNotDoneShotTaskEpisodeCodeList = $this->checkEpisodeEfxLightTaskDoneStatus($episode);
                if ($hasNotDoneShotTaskEpisodeCodeList['total'] > 0 && $hasNotDoneShotTaskEpisodeCodeList['undone'] == 0) {
                    // 有灯光特效任务 并且灯光特效任务都已完成
                    $this->updateEpisodeStatus($episode, $updateStatus);
                }
                break;
        }
    }

    /**
     * 更新剧集状态
     * @param $episode
     * @param $updateStatus
     * @return void
     * @throws \think\Exception
     */
    public function updateEpisodeStatus($episode, $updateStatus)
    {
        request()->getModuleCode('episode');
        $commonService = CommonService::instance('entity');
        $entityUpdateData = [
            'id' => $episode['id'],
            'episode_status' => $updateStatus['id'],
        ];
        $defaultStartStatus = StatusService::getInstance()->getTaskDefaultStartStatus();
        $defaultDoneStatus = StatusService::getInstance()->getTaskDoneStatus();

        if ($updateStatus['id'] == $defaultStartStatus['id']) {
            if ($episode['start_time'] == 0) {
                $entityUpdateData['start_time'] = time();
            }
        } elseif ($updateStatus['id'] == $defaultDoneStatus['id']) {
            $entityUpdateData['end_time'] = time();
        }
        $commonService->update($entityUpdateData, 'episode', false);
    }

    /**
     * @param $episode
     * @return array|false|mixed|string|null
     * @throws \think\Exception
     */
    private function checkEpisodeEfxLightTaskDoneStatus($episode)
    {
        $beforeChenPianStepCategoryList = model(StepCategoryModel::class)->where(['code' => ['IN', ['lighting', 'efx']]])->select();
        $beforeChenPianStepCategoryIdList = array_column($beforeChenPianStepCategoryList, 'id');
        return model(TaskModel::class)->alias('t')
            ->join("entity e on t.entity_id = e.id")
            ->where([
                "e.project_id" => $episode['project_id'],
                'e.module_id' => module_by_code('shot')['id'],
                't.step_type' => 'step', 'e.initial_episode_code' => $episode['code'],
                't.step_category_id' => ['IN', $beforeChenPianStepCategoryIdList],
            ])
            ->field("count(t.json->>'$.task_status' <> 7 or null) undone, count(t.id) total")
            ->find();
    }


}
